package com.megalith.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.megalith.constant.ResultCode;
import com.megalith.dto.CandidateGroupProcessDTO;
import com.megalith.dto.CandidateProcessInstanceBaseDTO;
import com.megalith.dto.TaskClaimDTO;
import com.megalith.service.CandidateGroupTaskService;
import com.megalith.vo.Result;
import com.megalith.vo.TaskEntityVO;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.IdentityService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.idm.api.Group;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description TODO
 * @Author lfp
 * @Date 2022/7/16
 * @Version 1.0
 */
@Slf4j
@Service
public class CandidateGroupTaskImpl implements CandidateGroupTaskService {
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private IdentityService identityService;

    @Override
    public Result startCandidateGroupProcess(CandidateGroupProcessDTO groupProcessDTO) {
        //为了简便，直接在创建流程的时候，给流程变量赋值（除了财务）
        Map<String, Object> param = new HashMap<>();
        //设置流程变量
        param.put("staff",groupProcessDTO.getStaff());
        param.put("days",groupProcessDTO.getDays());
        param.put("humanResources","10021");//为了简便，直接给人力资源流程变量赋值

        //设置部门经理审批、总经理审批两个任务节点的候选人组编号
        param.put("managerGroup",groupProcessDTO.getManagerGroupId());
        param.put("generalManagerGroup",groupProcessDTO.getGeneralManagerGroupId());

        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(groupProcessDTO.getProcessDefinitionKey(), param);

        log.info("候选人组流程实例启动成功，流程实例编号：{}，候选人组编号分别是：managerGroup->{},generalManagerGroup->{}",
                processInstance.getId(),groupProcessDTO.getManagerGroupId(),groupProcessDTO.getGeneralManagerGroupId());

        return Result.ok(processInstance.getId());
    }

    @Override
    public Result completePersonalProcess(CandidateProcessInstanceBaseDTO processInstanceDTO) {
        Task task = taskService.createTaskQuery()
                .processInstanceId(processInstanceDTO.getProcessInstanceId())
                .taskAssignee(processInstanceDTO.getAssignee())
                .active()
                .singleResult();

        if(task != null){
            taskService.complete(task.getId());
            return Result.ok(ResultCode.TASK_SUCCESS.getDes());
        }else {
            return Result.sysError("未查询到任务");
        }
    }

    @Override
    public List<TaskEntityVO> claimableTaskList(String userId) {
        List<TaskEntityVO> taskEntityVOList = new ArrayList<>();

        //先根据自己编号，查询自己所属的用户组
        Group group = identityService.createGroupQuery()
                .groupMember(userId)
                //因为群组信息中，用户编号是主键，不能重复，
                // 所以引擎自带表，单个用户只能加一个组
                .singleResult();

        if(group == null){
            return taskEntityVOList;
        }


        //再查询自己用户组可认领的任务
        List<Task> list = taskService.createTaskQuery()
                .taskCandidateGroup(group.getId())
                .active()
                .orderByTaskCreateTime()
                .asc()
                .list();

        taskEntityVOList = list.stream().map(task->{
            return BeanUtil.copyProperties(task,TaskEntityVO.class);
        }).collect(Collectors.toList());

        return taskEntityVOList;
    }

    @Override
    public Result claimGroupTask(TaskClaimDTO claimDTO) {
        Task groupTask = getCandidateGroupTask(claimDTO);
        if(groupTask == null){
            return Result.sysError("未查询到当前流程可认领的组任务!");
        }

        taskService.claim(groupTask.getId(),claimDTO.getUserId());

        return Result.ok("任务领取成功!");
    }

    @Override
    public Result unclaimGroupTask(TaskClaimDTO claimDTO) {
        //如果是已认领的任务，那么此时当前用户应该拥有此流程实例的待办任务
        Task task = taskService.createTaskQuery()
                .processInstanceId(claimDTO.getProcessInstanceId())
                .taskAssignee(claimDTO.getUserId())
                .active()
                .singleResult();

        if(task == null){
            return Result.sysError("未查询到任务!");
        }

        taskService.unclaim(task.getId());

        return Result.ok("任务归还成功");
    }


    /**
    *@Description 根据用户编号、流程实例编号，获取待认领组任务
    *@Author lfp
    *@Date 2022/7/17
    *@param claimDTO
    *@Return
    */
    public Task getCandidateGroupTask(TaskClaimDTO claimDTO){
        //校验，可以通过用户编号，查找到可认领的组任务，再进行流程实例比对
        Group group = identityService.createGroupQuery()
                .groupMember(claimDTO.getUserId())
                .singleResult();
        if(group==null){
            return null;
        }

        Task task = taskService.createTaskQuery()
                //通过用户所属组编号，以及流程实例编号，进行认领
                // （前端如果有多个可认领组任务，那么认领操作时，必须将流程实例编号和用户编号传递过来）
                .taskCandidateGroup(group.getId())
                .processInstanceId(claimDTO.getProcessInstanceId())
                .active()
                .singleResult();

        return task;
    }
}
